package com.lbc.controller;

import com.lbc.bean.dto.LoginDTO;
import com.lbc.bean.dto.RegisterDTO;
import com.lbc.bean.dto.ResetPasswordDTO;
import com.lbc.bean.entity.User;
import com.lbc.common.constants.Constants;
import com.lbc.common.resp.ResponseResult;
import com.lbc.common.utils.Captcha;
import com.lbc.common.utils.FileUtils;
import com.lbc.common.utils.JwtUtils;
import com.lbc.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import sun.misc.BASE64Encoder;

import javax.naming.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author xyl
 * @date 2021-03-03 9:06
 */
@Api(tags = "通用接口")
@RestController
@RequestMapping("lbc")
public class LbcController {
    @Autowired
    private UserService userService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private Captcha captcha;

    @ApiOperation("登陆接口")
    @PostMapping("login")
    public ResponseResult login(@RequestBody @Validated LoginDTO loginDTO, @ApiIgnore HttpServletRequest request) {
        //todo 图形验证码
//        String captchaCode = stringRedisTemplate.opsForValue().get(Constants.REDIS_KEY_CAPTCHA_PREFIX + request.getSession().getId());
//        if(!loginDTO.getCaptchaCode().equalsIgnoreCase(captchaCode)){
//            return ResponseResult.error("验证码有误!");
//        }
        User user = userService.getUserByEmail(loginDTO.getEmail());
        if (ObjectUtils.isEmpty(user)) {
            return ResponseResult.error("邮箱不存在 , 请进行注册!");
        } else if (!user.getPassword().equalsIgnoreCase(loginDTO.getPassword())) {
            return ResponseResult.error("密码不匹配!");
        } else if (Constants.USER_STATE1 != user.getState()) {
            if (Constants.USER_STATE0 == user.getState()) {
                return ResponseResult.error("账号正在审核中...");
            }
            return ResponseResult.error("请联系管理员 , 当前用户状态不允许登录!");
        }
        String token = JwtUtils.signObject(user);
        Date lastLoginTime = (Date) redisTemplate.opsForValue().get(Constants.REDIS_KEY_LAST_TIME_PREFIX + user.getUserId());
        if(ObjectUtils.isNotEmpty(lastLoginTime)){
            //登录成功 修改上次登录时间
            userService.modifyUserLastLoginTime(user.getUserId(),lastLoginTime);
        }
        redisTemplate.opsForValue().set(Constants.REDIS_KEY_LAST_TIME_PREFIX + user.getUserId(), new Date());
        stringRedisTemplate.opsForValue().set(Constants.REDIS_KEY_TOKEN_PREFIX + token, user.getUserId().toString(), Constants.TOKEN_EXPIRE_TIME, TimeUnit.HOURS);
        return ResponseResult.success(token);
    }

    @ApiOperation("管理后台登陆接口")
    @PostMapping("/admin/login")
    public ResponseResult adminLogin(@RequestBody @Validated LoginDTO loginDTO, @ApiIgnore HttpServletRequest request) throws AuthenticationException {
        User user = userService.getUserByEmail(loginDTO.getEmail());
        if (ObjectUtils.isEmpty(user)) {
            return ResponseResult.error("邮箱不存在 , 请进行注册!");
        } else if (!user.getPassword().equalsIgnoreCase(loginDTO.getPassword())) {
            return ResponseResult.error("密码不匹配!");
        } else if (Constants.USER_STATE1 != user.getState()) {
            if (Constants.USER_STATE0 == user.getState()) {
                return ResponseResult.error("账号正在审核中...");
            }
            return ResponseResult.error("请联系管理员 , 当前用户状态不允许登录!");
        }else if(user.getRoleId() == Constants.ROLE_USER){
            throw new AuthorizationException("无权限");
        }
        String token = JwtUtils.signObject(user);
        Date lastLoginTime = (Date) redisTemplate.opsForValue().get(Constants.REDIS_KEY_LAST_TIME_PREFIX + user.getUserId());
        if(ObjectUtils.isNotEmpty(lastLoginTime)){
            //登录成功 修改上次登录时间
            userService.modifyUserLastLoginTime(user.getUserId(),lastLoginTime);
        }
        redisTemplate.opsForValue().set(Constants.REDIS_KEY_LAST_TIME_PREFIX + user.getUserId(), new Date());
        stringRedisTemplate.opsForValue().set(Constants.REDIS_KEY_TOKEN_PREFIX + token, user.getUserId().toString(), Constants.TOKEN_EXPIRE_TIME, TimeUnit.HOURS);
        return ResponseResult.success(token);
    }

    @ApiOperation("注册")
    @PostMapping("register")
    public ResponseResult register(@RequestBody @Validated RegisterDTO registerDTO) {
        //先验证邮箱码
        String s = stringRedisTemplate.opsForValue().get(Constants.REDIS_KEY_REGISTER_EMAIL_PREFIX + registerDTO.getEmail());
        if (!registerDTO.getEmailCode().equalsIgnoreCase(s)) {
            return ResponseResult.error("验证码不匹配!");
        }
        User userByEmail = userService.getUserByEmail(registerDTO.getEmail());
        if (ObjectUtils.isNotEmpty(userByEmail) && userByEmail.getState() == 1) {
            return ResponseResult.error("此邮箱 :" + registerDTO.getEmail() + ",已存在请进行登录!");
        }
        User temp = new User();
        BeanUtils.copyProperties(registerDTO, temp);
        return ResponseResult.toResponse(userService.add(temp));
    }

    @ApiOperation("发送邮箱验证码 , 注册时进行发送")
    @PostMapping("/send/mail")
    public ResponseResult sendMail(@RequestParam String mail) {

        if (StringUtils.isEmpty(mail)) {
            return ResponseResult.error("mail不能为null");
        }
        User userByEmail = userService.getUserByEmail(mail);
        if (ObjectUtils.isNotEmpty(userByEmail)) {
            return ResponseResult.error("此邮箱 :" + mail + ",已存在请进行登录!");
        }
        userService.sendMail(mail, Constants.REDIS_KEY_REGISTER_EMAIL_PREFIX + mail);
        //todo 默认返回为成功
        return ResponseResult.success();
    }

    @ApiOperation("发送邮箱验证码 , 重置密码进行发送")
    @PostMapping("/send/mail2")
    public ResponseResult sendMail2(@RequestParam String mail) {
        if (StringUtils.isEmpty(mail)) {
            return ResponseResult.error("mail不能为null");
        }
        User userByEmail = userService.getUserByEmail(mail);
        if (ObjectUtils.isEmpty(userByEmail)) {
            return ResponseResult.error("此邮箱 :" + mail + ",不存在!");
        }
        userService.sendMail(mail, Constants.REDIS_KEY_RESET_PASSWORD_PREFIX + mail);
        //todo 默认返回为成功
        return ResponseResult.success();
    }

    @ApiOperation("重置密码")
    @PostMapping("/reset/password")
    public ResponseResult resetPassword(@RequestBody  ResetPasswordDTO resetPasswordDTO){
        String code = stringRedisTemplate.opsForValue().get(Constants.REDIS_KEY_RESET_PASSWORD_PREFIX + resetPasswordDTO.getMail());
        if(!resetPasswordDTO.getMailCode().equalsIgnoreCase(code)){
            return ResponseResult.error("验证码错误!");
        }
        return ResponseResult.toResponse(userService.resetPassword(resetPasswordDTO));
    }


    @ApiOperation("获取图片验证码接口")
    @GetMapping("captcha")
    public ResponseResult getCaptcha(HttpServletRequest request) {
        String verifyCode = captcha.generateVerifyCode(4);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            captcha.outputImage(100, 40, outputStream, verifyCode);
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        String imageStr = encoder.encode(outputStream.toByteArray());
        System.out.println("验证码:" + verifyCode);
        stringRedisTemplate.opsForValue().set(Constants.REDIS_KEY_CAPTCHA_PREFIX + request.getSession().getId(), verifyCode, Constants.CAPTCHA_EXPIRE_TIME, TimeUnit.MINUTES);
        return ResponseResult.success(imageStr);
    }


    /**
     * 退出
     */
    @ApiOperation(value = "退出系统")
    @GetMapping("/logout")
    public ResponseResult logout(HttpServletRequest request) {
        String token = request.getHeader("token");
        if (StringUtils.isNotEmpty(token)) {
            //验证是否存key , 如果存在就直接在删除
            String s = stringRedisTemplate.opsForValue().get(token);
            if (StringUtils.isNotEmpty(s)) {
                Boolean delete = stringRedisTemplate.delete(token);
            }
        }
        return ResponseResult.success();
    }

    @ApiOperation("通用上传图片接口 ，上传图片为base64格式")
    @PostMapping("/upload/image")
    public ResponseResult uploadImage(@RequestParam String base64Image) {
        String s = FileUtils.Base64ToImage(Constants.NATIVE_IMAGE_PATH, base64Image);
        if (StringUtils.isEmpty(s)) {
            return ResponseResult.error("格式有误！");
        }
        return ResponseResult.success(Constants.VIRTUAL_IMAGE_PATH + s);
    }
}